﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using MS.InformationManagement.Core.Actions.Informado;
using MS.InformationManagement.Core.Support;
using MS.InformationManagement.Support;
using MS.InformationManagement.Support.Constants;
using MS.InformationManagement.Support.Exceptions;

namespace MS.InformationManagement.Core.Actions
{
    public class InformationAction : BaseAction, ICommand
    {

        #region [Private Fields]

        Dictionary<string, string> _viewers;
        StringBuilder _sbErrors;
        private Stack<ICommand> _commands;
        private Stack<SendEmailCommand> _emailCommands;

        #endregion

        #region Constructors

        public InformationAction(int[] selectedItems, Guid sourceLibrary)
            : base(selectedItems, sourceLibrary)
        {
            _viewers = new Dictionary<string, string>();
            _viewers.Add(GlobalConstants.CTTN_RADICADO_INTERNO, "/_layouts/MS.InformationManagement.WP/RadicadoInterno.aspx");
            _viewers.Add(GlobalConstants.CTTN_RADICADO_PERSONA, "/_layouts/MS.InformationManagement.WP/InsertarRadicado.aspx");
            _viewers.Add(GlobalConstants.CTTN_RADICADO_EMPRESA, "/_layouts/MS.InformationManagement.WP/InsertarRadicado.aspx");
            _viewers.Add(GlobalConstants.CTTN_RADICADO_EMPRESA_SALIDA, "/_layouts/MS.InformationManagement.WP/InsertarRadicadoSalida.aspx");
            _viewers.Add(GlobalConstants.CTTN_RADICADO_PERSONA_SALIDA, "/_layouts/MS.InformationManagement.WP/InsertarRadicadoSalida.aspx");
            _sbErrors = new StringBuilder();
            _commands = new Stack<ICommand>();
            _emailCommands = new Stack<SendEmailCommand>();
        }

        #endregion

        #region [BaseAction Members]

        public override void Execute(string targetUser)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite currentSite = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb currentWeb = currentSite.OpenWeb())
                    {

                        currentSite.AllowUnsafeUpdates = true;
                        currentWeb.AllowUnsafeUpdates = true;

                        SPList targetLibrary = UserLibraryHelper.GetUserList(targetUser, currentWeb);
                        if (targetLibrary == null)
                            throw new Exception("No se encuentra el usuario");

                        try
                        {
                            for (int i = 0; i < this.SelectedIds.Length - 1; i++)
                            {
                                SPFolder sourceFolder = this.SourceLibrary.GetItemById(this.SelectedIds[i]).Folder;
                                string target = PeopleHelper.GetUserByLoginName(targetUser).User.Name;
                                int docsCount = this.getDocumentsPostFix(sourceFolder.Name, targetLibrary);
                                string newDocumentName = sourceFolder.Name + "-" + docsCount + 1;

                                if (documentExistsInTarget(targetLibrary, newDocumentName))
                                    throw new Exception(string.Format("El documento ya habia sido informado al usuario {0}", targetLibrary));
                                else
                                {
                                    UpdateSourceDocumentCommand uCommand = new UpdateSourceDocumentCommand(sourceFolder, target, SPContext.Current.Web);
                                    uCommand.Execute();
                                    _commands.Push(uCommand);
                                    AssignDocumentCommand aCommand = new AssignDocumentCommand(newDocumentName, _viewers, sourceFolder, SourceLibraryId, targetLibrary, SPContext.Current.Web);
                                    aCommand.Execute();
                                    _commands.Push(aCommand);
                                    SPFile newAssignment = aCommand.Item;
                                    SendEmailCommand eCommand = new SendEmailCommand(SPContext.Current.Web.CurrentUser, PeopleHelper.GetUserByLoginName(targetUser).User,
                                            sourceFolder.Item, newAssignment.Item.ID, newAssignment.Item.ParentList.ID.ToString()
                                            , newAssignment.Item.ContentType.Name, false, currentWeb);
                                    _emailCommands.Push(eCommand);
                                }
                            }

                            while (_emailCommands.Count != 0) { _emailCommands.Pop().Execute(); }
                        }
                        catch (NotificationException) { throw; }
                        catch (Exception)
                        {
                            Undo();
                            throw;
                        }                        
                        finally{
                            currentSite.AllowUnsafeUpdates = false;
                            currentWeb.AllowUnsafeUpdates = false;
                        }
                    }
                }
            });
        } 

        #endregion

        #region [Private Members]

        private bool documentExistsInTarget(SPList targetList, string documentName)
        {
            bool result = false;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite currentSite = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb currentWeb = currentSite.OpenWeb())
                    {
                        SPList currentList = currentWeb.Lists[targetList.ID];
                        string camlQuery = string.Format("<Where><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>{0}</Value></Eq></Where>", documentName);
                        SPQuery query = new SPQuery() { Query = camlQuery };
                        result = currentList.GetItems(query).Count > 0;
                    }
                }
            });

            return result;
        } 

        #endregion

        #region [ICommand Members]
        
        public void Undo()
        {
            while (_commands.Count != 0) { _commands.Pop().Undo(); }
        }
 
        #endregion
    }
}
